package com.yy.young.common.web;

import com.yy.young.common.core.excel.ExcelExport;
import com.yy.young.common.core.excel.ExcelImport;
import com.yy.young.common.core.excel.IExcelExport;
import com.yy.young.common.core.excel.IExcelImport;
import com.yy.young.common.service.ICommonService;
import com.yy.young.common.util.CommonUtil;
import com.yy.young.common.util.Result;
import com.yy.young.common.util.StringUtils;
import com.yy.young.dal.util.Page;
import com.yy.young.interfaces.log.annotation.Log;
import com.yy.young.interfaces.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 公共请求处理
 * Created by rookie on 2018/3/12.
 */
public abstract class AbstractCommonController<T> implements InitializingBean {

    protected ICommonService<T> service;

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 初始化服务
     */
    public abstract void initService();

    /**
     * 根据请求获取服务
     * @param request
     * @return
     */
    public abstract ICommonService<T> getServiceFromRequest(HttpServletRequest request);


    /**
     * 对参数做处理,返回最终的入参,在调用service前执行
     * 在执行查询/修改/插入等有关模型类传参的操作时调用此回调函数对传参做自定义处理
     * @param param 待传入service的参数
     * @param request
     */
    public abstract T backFinalParameter(T param, HttpServletRequest request);

    /**
     * 内部使用的获取服务方法
     * @param request
     * @return
     */
    private ICommonService<T> getService(HttpServletRequest request){
        if (this.service != null){
            return this.service;
        }else{
            ICommonService<T> s = this.getServiceFromRequest(request);//根据请求获取对应服务
            if (s != null){
                return s;
            }else{
                throw new RuntimeException("查找服务失败!");
            }
        }
    }

    /**
     * 内部使用的参数处理,返回最终参数
     * 在执行查询/修改/插入等有关模型类传参的操作时调用此回调函数对传参做自定义处理
     * @param param
     * @param request
     * @return
     */
    private T handleParameter(T param, HttpServletRequest request){
        //调用回调backFinalParameter
        return backFinalParameter(param, request);
    }

    /**
     * bean初始化后调用,实现InitializingBean接口
     * @throws Exception
     */
    public void afterPropertiesSet() throws Exception{
        this.initService();
        if (this.service != null){
            logger.debug("AbstractCommonController's sub [{}] instance init : service init success.", this.getClass().getName());
        }else{
            logger.warn("AbstractCommonController's sub [{}] instance init : service init fail.", this.getClass().getName());
        }
    }

    /**
     * 获取当前登陆用户
     * @param request
     * @return
     */
    public User getLoginUser(HttpServletRequest request){
        return CommonUtil.getLoginUser(request);
    }

    /**
     * 查询列表
     * @param obj
     * @param request
     * @return
     * @throws Exception
     */
    @Log("查询列表")
    @RequestMapping("/getList")
    @ResponseBody
    public Object getList(T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        List<T> list = service.getList(obj);
        return new Result(list);
    }

    /**
     * 分页查询列表
     * @param obj
     * @param request
     * @return
     * @throws Exception
     */
    @Log("分页查询列表")
    @RequestMapping("/getPage")
    @ResponseBody
    public Object getPage(T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        Page page = CommonUtil.getPageFromRequest(request);
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        List<T> list = service.getPage(obj, page);
        page.setData(list);
        return page;
    }

    /**
     * 查询单条
     * @param obj
     * @param request
     * @return
     * @throws Exception
     */
    @Log("查询单条")
    @RequestMapping("/get")
    @ResponseBody
    public Object getPoint(T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        return new Result(service.get(obj));
    }

    /**
     * 新增
     * @param obj
     * @param request
     * @return
     * @throws Exception
     */
    @Log("新增")
    @RequestMapping("/insert")
    @ResponseBody
    public Object insert(T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        service.insert(obj);
        return new Result();
    }

    /**
     * 修改
     * @param obj
     * @param request
     * @return
     * @throws Exception
     */
    @Log("修改")
    @RequestMapping("/update")
    @ResponseBody
    public Object update(T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        service.update(obj);
        return new Result();
    }

    /**
     * 删除
     * @param ids
     * @param id
     * @param request
     * @return
     * @throws Exception
     */
    @Log("删除")
    @RequestMapping("/delete")
    @ResponseBody
    public Object delete(String ids, String id, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        Result result = new Result();
        if(StringUtils.isNotBlank(ids)) {
            String[] idArr = ids.split(",");
            service.delete(idArr);
        }else if(StringUtils.isNotBlank(id)){
            service.delete(id);
        }else{
            result.setCode(-1);
            result.setInfo("删除失败:待删除编号无效!");
        }
        return result;
    }

    /**
     * 导入
     * @param file
     * @param obj 用于获取class,无实际意义
     * @param request
     * @return
     * @throws Exception
     */
    @Log("导入")
    @RequestMapping("/import")
    @ResponseBody
    public Object importExcel(MultipartFile file, T obj, HttpServletRequest request) throws Exception{
        ICommonService<T> service = getService(request);//获取服务
        Result result = new Result();
        try {
            if (file != null && !file.isEmpty()) {
                //excel导入处理,返回excel中的数据集合
                IExcelImport ei = new ExcelImport(file);//将文件转为ExcelImport对象
                List<?> list = null;
                if (obj instanceof Map){
                    list = ei.getImportData();
                }else{
                    list = ei.getImportDataAsBean(obj.getClass());
                }
                if (list != null && list.size() > 0){
                    int num = service.batchInsert((List<T>) list);//批量插入
                    result.setInfo("成功导入数据" + num + "条!");
                }else {
                    result.setCode(-1);
                    result.setInfo("导入失败:excel解析后结果为空!");
                }
            } else {
                result.setCode(-1);
                result.setInfo("导入失败:文件为空!");
            }
        } catch (IOException e) {
            e.printStackTrace();
            result.setCode(-1);
            result.setInfo("导入失败!");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            result.setCode(-1);
            result.setInfo("导入失败!");
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(-1);
            result.setInfo("导入失败!");
        }
        return result;
    }

    /**
     * 导出
     * @param obj 用于获取class以及作为查询的参数
     * @param request
     * @param response
     * @throws Exception
     */
    @Log("导出")
    @RequestMapping("/export")
    public void exportExcel(T obj, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (obj instanceof Map){
            throw new UnsupportedOperationException("被导出实体类为Map类型,需要重写导出方法 public void exportExcel(T obj, HttpServletRequest request, HttpServletResponse response) throws Exception {}");
        }
        ICommonService<T> service = getService(request);//获取服务
        obj = handleParameter(obj, request);//调用service前对参数做自定义处理
        List list = service.getList(obj);
        if (list != null && list.size() > 0){
            IExcelExport ee = new ExcelExport();
            ee.insertBeanList(list, obj.getClass());
            ee.write2Response(response, "excel_" + System.currentTimeMillis() + ".xls");
        }
    }
}
